'''
Usage:
    client.py
    client.py <ip> <port>

Options:
    -h --help show this

Example:
    client.py(defualt ip is 127.0.0.1 and port is 10000)
    client.py <ip> <port>
'''

# !/usr/bin/env python3
# -*- coding: utf-8 -*-
# aim:    
# author: wangkaixuan
# email:  26554189525@qq.com 
# date:   2018/1/15

from socket import *
from docopt import docopt

# HOST = '192.168.137.1'
HOST = '127.0.0.1'
PORT = 9898
BUFSIZE = 1024
ADDR = (HOST, PORT)

def use_Tcp():
    TcpCliSock = socket(AF_INET,SOCK_STREAM)
    TcpCliSock.connect(ADDR)
    while(True):
        data = input('>>>')
        if not data:
            break
        TcpCliSock.send(data.encode())
        data = TcpCliSock.recv(BUFSIZE).decode()
        if not data:
            break
        print(data)
    TcpCliSock.close()

def use_Udp():
    udpCliSock = socket(AF_INET, SOCK_DGRAM)
    while(True):
        data = input('>>>')
        if not data:
            break
        udpCliSock.sendto(data.encode(),ADDR)
        data,addr = udpCliSock.recvfrom(BUFSIZE)
        if data:
            print(data.decode())
            print(addr)
    udpCliSock.close()

# from socketserver import (TCPServer as TCP,StreamRequestHandler as SRH)
def use_SocketServer():
    while(True): 
        TcpCliSock = socket(AF_INET,SOCK_STREAM)
        TcpCliSock.connect(ADDR)
        data = input('>>>')
        if not data:
            break
        data = data + '\r\n'
        TcpCliSock.send(data.encode())
        data = TcpCliSock.recv(BUFSIZE)
        if not data:
            break
        print('recv data:',data.decode())
        TcpCliSock.close()

def use_Twisted():
    from twisted.internet import protocol,reactor
    class TSClntProtocol(protocol.Protocol):
        def sendData(self):
            data = input('>>>')
            if data:
                print('send data:',data)
                self.transport.write(data.encode())
            else:
                self.transport.lostConnection()
        def connectionMade(self):
            self.sendData()
        def dataReceived(self,data):
            print('recv data:',data)
            self.sendData()
    class TSClntFactory(protocol.ClientFactory):
        protocol = TSClntProtocol
        clientConnectionLost = clientConnectionFailed =lambda self,connector,reason:reactor.stop()
    reactor.connectTCP(HOST,PORT,TSClntFactory())
    reactor.run()

def use_Twisted_ex2_4(HOST,PORT):
    from twisted.internet import protocol,reactor
    class TSClntProtocol(protocol.Protocol):
        def sendData(self):
            data = input('>>>')
            if data:
                self.transport.write(data.encode())
            else:
                self.transport.lostConnection()
        def connectionMade(self):
            self.sendData()
        def dataReceived(self,data):
            print(data.decode())
            self.sendData()
    class TSClntFactory(protocol.ClientFactory):
        protocol = TSClntProtocol
        clientConnectionLost = clientConnectionFailed =lambda self,connector,reason:reactor.stop()
    reactor.connectTCP(HOST,int(PORT),TSClntFactory())
    reactor.run()

def ex2_4():
    arguments = docopt(__doc__)
    use_Twisted_ex2_4(arguments.get('<ip>'),arguments.get('<port>'))

def ex2_5():
    ex2_4()

def ex2_6():
    arguments = docopt(__doc__)
    udpCliSock = socket(AF_INET, SOCK_DGRAM)
    while(True):
        data = input('>>>')
        if not data:
            break
        if data == 'q':
            sys.exit()
        addr = (arguments.get('<ip>'),int(arguments.get('<port>')))
        print('addr=',addr)
        udpCliSock.sendto(data.encode(),addr)
        data,addr = udpCliSock.recvfrom(BUFSIZE)
        if data:
            print(data.decode())
            print(addr)
    udpCliSock.close()
ex2_6()